/**
 * ConfigLoaderSupport.java
 * 卢晓峰
 * Email：lxf9601@gmail.com
 * QQ：297051898
 * Created by 2010-6-6
 */
package com.autoabacus.core.config;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.tree.DefaultAttribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.autoabacus.core.config.component.Command;
import com.autoabacus.core.config.component.Field;
import com.autoabacus.core.config.component.Table;
import com.autoabacus.core.config.exception.ConfigFileNotFoundException;
import com.autoabacus.core.config.protocol.CommandProtocol;
import com.autoabacus.core.config.protocol.FieldProtocol;
import com.autoabacus.core.config.protocol.TableProtocol;
import com.autoabacus.core.config.protocol.TableProtocol.Type;

/**
 * 配置加载支持类
 * @author 卢晓峰
 */
@SuppressWarnings("unchecked")
public class ConfigLoaderSupport implements ConfigLoader {
	public Logger logger = LoggerFactory.getLogger(ConfigLoaderSupport.class);
	
	public static final String ROOT_ELEMENT = "config";
	
	public static final String TABLE_ELEMENT = "table";
	
	public static final String VARIABLE_ELEMENT = "variable";
	
	public static final String FIELD_ELEMENT = "field";
	
	public static final String FIELDS_ELEMENT = "fields";
	
	public static final String COMMAND_ELEMENT = "command";
	
	public static final String COMMANDS_ELEMENT = "commands";
	
	public static final String TEMPLATE_ELEMENT = "template";
	
	
	private Config config = new Config();
	
	private Logger log = LoggerFactory.getLogger(ConfigLoaderSupport.class);
	
	/* (non-Javadoc)
	 * @see com.firstbuilder.config.core.ConfigLoader#loadConfig(java.lang.String)
	 */
	@Override
	public Config loadConfig(String configDirectory) throws ConfigFileNotFoundException {
		
		// xml读取器
		SAXReader reader = new SAXReader();
		
		// 配置文件目录
		File configDir = new File(configDirectory);
		
		// 目录不存在
		if (! configDir.exists()) {
			log.error("配置目录路径不存在 ！{}", configDir.getAbsolutePath());
			throw new ConfigFileNotFoundException("配置目录路径不存在 ！" + configDir.getAbsolutePath());
		}
		System.out.println(configDir);
		log.debug("加载配置路径:{}", configDir.getAbsolutePath());
		System.out.println("日");
		File[] files = configDir.listFiles();
		for (File file : files) {
			if (file.getName().endsWith(".xml")) {
				try {
					Document document = reader.read(file);
					parseDocument(document);
				} catch (DocumentException e) {
					logger.error("文件:{},文档解析错误!", file.getAbsolutePath() ,e);
				}
			}
		}
		
		return config;
	}
	
	/**
	 * 解析xml文档
	 * @param document
	 */
	protected void parseDocument(Document document)
	{
		List<Element> elements = (List<Element>)document.getRootElement().elements();
		for (Element element  : elements) {
			if (element.getName().equals(TABLE_ELEMENT)) {
				parseTable(element);
			} else if (element.getName().equals(TEMPLATE_ELEMENT)) {
				
			}
		}
	}
	
	/**
	 * 解析table元素
	 * @param element
	 * @return
	 */
	private Table parseTable(Element element) {
		// 构建table对象
		Table table = new Table();
		String tableName = element.attribute(TableProtocol.Attribute.NAME).getValue();
		// 缓存
		config.getTables().put(tableName, table);
		
		// 解析属性值
		for (DefaultAttribute attr : (List<DefaultAttribute>)element.attributes()) {
			if (attr.getName().equals(TableProtocol.Attribute.ALIAS)) {
				table.setAlias(attr.getValue());
			} else if (attr.getName().equals(TableProtocol.Attribute.TYPE)) {
				table.setType(Type.valueOf(attr.getName()));
			} else if (attr.getName().equals(TableProtocol.Attribute.TEMPLATE_NAME)) {
				table.setTemplateName(attr.getValue());
			} else if (attr.getName().equals(TableProtocol.Attribute.NAME)) {
				table.setName(attr.getValue());
			}
		}
		
		// 解析子元素
		for (Element childElement : (List<Element>)element.elements()) {
			if (childElement.getName().equals(FIELDS_ELEMENT)) {
				table.setFields(parseFields(table, childElement));
			} else if (childElement.getName().equals(COMMANDS_ELEMENT)) {
				table.setCommands(parseCommands(table, childElement));
			}
		}
		return table;
	}
	
	/**
	 * 解析字段集合
	 * @param element
	 * @return
	 */
	private LinkedHashMap<String, Field> parseFields(Table table, Element element) {
		LinkedHashMap<String, Field> fields = new LinkedHashMap<String, Field>();
		for (Element childElement : (List<Element>)element.elements()) {
			if (childElement.getName().equals(FIELD_ELEMENT)) {
				Field field = parseField(table, childElement);
				fields.put(field.getName(), field);
			}
		}
		return fields;
	}
	
	/**
	 * 解析字段
	 * @param element
	 * @return
	 * @throws NoSuchFieldException 
	 * @throws SecurityException 
	 */
	private Field parseField(Table table, Element element) {
		Field field = new Field();
		
		for (DefaultAttribute attr : (List<DefaultAttribute>)element.attributes()) {
			if (attr.getName().equals(FieldProtocol.Attribute.NAME)) {
				field.setName(attr.getValue());
			} else if (attr.getName().equals(FieldProtocol.Attribute.ALIAS)) {
				field.setAlias(attr.getValue());
			} else if (attr.getName().equals(FieldProtocol.Attribute.PRIMARY_KEY)) {
				field.setPrimaryKey(Boolean.valueOf(attr.getValue()));
			} else if (attr.getName().equals(FieldProtocol.Attribute.DATA_TYPE)) {
				field.setDataType(FieldProtocol.DataType.valueOf(attr.getValue()));
			} else if (attr.getName().equals(FieldProtocol.Attribute.LINK)) {
				field.setLink(attr.getValue());
			} else if (attr.getName().equals(FieldProtocol.Attribute.REF)) {
				
			} else if (attr.getName().equals(FieldProtocol.Attribute.VIEW_STRATEGY)) {
				field.setViewStrategy(FieldProtocol.ViewStrategy.valueOf(attr.getValue()));
			} else if (attr.getName().equals(FieldProtocol.Attribute.QUERY_STRATEGY)) {
				field.setQueryStrategy(FieldProtocol.QueryStrategy.valueOf(attr.getValue()));
			} else if (attr.getName().equals(FieldProtocol.Attribute.SORT_INDEX)) {
				field.setSortIndex(Integer.valueOf(attr.getValue()));
			} else if (attr.getName().equals(FieldProtocol.Attribute.DICTIONARY_NAME)) {
				
			} 
		}
		
		return field;
	}
	
	/**
	 * 解析功能指令集合
	 * @param element
	 * @return
	 */
	private LinkedHashMap<String, Command> parseCommands(Table table, Element element) {
		LinkedHashMap<String, Command> commands = new LinkedHashMap<String, Command>();
		for (Element childElement : (List<Element>)element.elements()) {
			if (childElement.getName().equals(COMMAND_ELEMENT)) {
				Command command = parseCommand(table, childElement);
				commands.put(command.getName(), command);
			}
		}
		return commands;
	}
	
	/**
	 * 解析功能指令
	 * @param table
	 * @param element
	 * @return
	 */
	private Command parseCommand(Table table, Element element) {
		Command command = new Command();
		command.setTable(table.getName());
		for (DefaultAttribute attr : (List<DefaultAttribute>)element.attributes()) {
			if (attr.getName().equals(CommandProtocol.Attribute.NAME)) {
				command.setName(attr.getValue());
			} else if (attr.getName().equals(CommandProtocol.Attribute.COMMAND_TYPE)) {
				command.setType(CommandProtocol.Type.valueOf(attr.getValue()));
			} else if (attr.getName().equals(CommandProtocol.Attribute.ALIAS)) {
				command.setAlias(attr.getValue());
			} else if (attr.getName().equals(CommandProtocol.Attribute.EFFECT_TABLE)) {
				command.setEffectTable(attr.getValue());
			} else if (attr.getName().equals(CommandProtocol.Attribute.USER_RANGE)) {
				command.setUseRange(CommandProtocol.UseRange.valueOf(attr.getValue()));
			} else if (attr.getName().equals(CommandProtocol.Attribute.SHOW_CONFIRM)) {
				command.setShowConfirm(Boolean.valueOf(attr.getValue()));
			}
		}
		
		if (command.getEffectTable() == null) {
			command.setEffectTable(table.getName());
		}
		
		return command;
	}
}
